/**
 * 插件封装
 * 有的插件是传js，不需要样式；有的插件是需要样式支持的，样式如何处理：
 * +全部写在插件中，一般以行内样式的方法，写给对应创建的元素。这样别人调用产检的时候，方便一些，直接导入js即可，可以不管样式；插件中的代码乱，不方便后期用户自定义样式
 * +也可以在插件中动态创建link，导入外部资源样式
 * +js和css分离,需要用户单独导入css，导入的样式要避免和现有的样式冲突，但是用户可以自己基于观看插件样式，进行样式的二次配置
 * 
 * 进行呢任何插件/类库/框架的封装，最好都采用OOP面向对象模式
 * +可以创建类的实例，实例是单独的
 * +实例具备私有的属性，也具备一些公共的方法
 * +还可以基于继承等方式，实现多个插件之间的关联
 */
(function(){
  // 封装插件的时候，我们需要支持n多的配置项，有的配置项不传递有默认值：此时我们千万不要一个个定义形参，而是采用对象的方法（可以不传，可以不用换考虑传递的顺序=-》参数三个以上最好用对象）
  function ModalPlugin(options){
    return new init(options)
  }

  // 类的原型：公共的属性方法
  ModalPlugin.prototype = {
    contructor: ModalPlugin,
    // 相当于大脑。可以控制先干什么再干什么
    init(){
      // 创建DOM结构
      this.createDOM()

      // 基于事件委托实现点击事件的处理
      this.dpnDialog.addEventListener('click', ev=>{
        let target = ev.target,
        targetTag = target.tagName

        // 点击关闭按钮
        if(targetTag === 'I' && target.className.includes('dpn-close')){
          this.close()
          return
        }
        // 点击的是底部按钮
        if(targetTag === 'BUTTON' && target.parentNode.className.includes('dpn-handle')){
          let index = target.getAttribute('index')
          let func = this.options.buttons[index]['click']
          if(typeof func === 'function') {
            func.call(this)
          }

        }
      })

      this.fire('init')
    },
    // 创建DOM结构
    createDOM(){
      let {title, template, buttons} = this.options
      let frag = document.createDocumentFragment()
      let dpnDialog = document.createElement('div')
      dpnDialog.className = 'dpn-dialog'
      dpnDialog.innerHTML = `
      <div class='dpn-title'>
        ${title}
        <i class="dpn-close">X</i>
      </div>
      <div class="dpn-content">
        ${typeof template === 'object' && template.nodeType?template.outerHTML():template}
      </div>
      ${
        buttons.length > 0? `
        <div class="dpn-handle">
      ${buttons.map((item,index) => {return `<button index='${index}'>${item.text}</button>`}).join('')}
        </div>
        `: ''
      }
      `

      let dpnModel = document.createElement('div')
      dpnModel.className = 'dpn-model'

      frag.appendChild(dpnDialog)
      frag.appendChild(dpnModel)

      document.body.appendChild(frag) // 创建元素优化
      frag = null
      this.dpnDialog = dpnDialog
      this.dpnModel = dpnModel

    },

    // 控制显隐
    open () {
      this.dpnDialog.style.display = 'block'
      this.dpnModel.style.display = 'block'
      this.fire('open')
    },
    close () {
      this.dpnDialog.style.display = 'none'
      this.dpnModel.style.display = 'none'
      this.fire('close')
    },

    // on向事件池中订阅方法
    on(type,func){
      let arr = this.pond[type]
      if(arr.includes(func)){
        return
      }
      arr.push(func)
    },
    // 通知事件池中的方法执行
    fire(type) {
      let arr = this.pond[type]
      arr.forEach(item => {
        if(typeof item === 'function') {
          item.call(this)
        }
      })
    }
  }
  // 创建实例，让实例找到公共的属性方法
  function init (options) {
    // 参数初始化：用传递进来的配置项替换默认的配置项
    options = Object.assign({
      title: '系统提示', //  标题
      template: '', // 内容模板
      drag: true, // 拖拽
      buttons: [ // 自定义按钮
        {
          text: '确定',
          click(){}
        },
        {
          text: '取消',
          click(){}
        }
      ]
    }, options)
    // 把信息挂载到实例上：在原型等各个方法中，只要this是实例，都可以调用到这些信息
    this.options = options
    // 事件池
    this.pond = {
      init:[],
      close:[],
      open:[],
    }
    this.init()
  }
  init.prototype = ModalPlugin.prototype

  // 浏览器直接导入，这样的方法是暴露到全局
  window.ModalPlugin = ModalPlugin

  // 还需要支持ES6Module/CommonJS模块导入规范  (webpack  自带module)
  if (typeof module !== 'undefined' && typeof module.exports  !== 'undefined') {
    module.exports = ModalPlugin
  }
  
})(window);

ModalPlugin({
  title: '系统提示', //  标题
  template: `<div>123123123</div>`, // 内容模板
  drag: false, // 拖拽
  buttons: [ // 自定义按钮
    {
      text: '确定',
      click(){}
    }
  ]
})
/*
 let modal = ModalPlugin({
   title: '系统提示', //  标题
   template: null, // 内容模板
   drag: false, // 拖拽
   buttons: [ // 自定义按钮
     {
       text: '确定',
       click(){}
     }
   ]
 })

 modal.open() // 打开
 modal.close() // 关闭

 modal.on('init/open/close/dragstart/dragmove/dragend',[func]) // 监听
 */